package think.in.java.concurrency.PractiseOneMoreTime;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by richard on 5/4/14.
 */
public class Exersice23WaxWithNotify {
    public static void main(String[ ] args){
        ExecutorService executorService =    Executors.newFixedThreadPool(2);
        Car car = new Car();
        executorService.execute(new WaxOn(car));
        executorService.execute(new WaxOff(car));
        car = new Car();
        executorService.execute(new WaxOn(car));
        executorService.execute(new WaxOff(car));
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        executorService.shutdownNow();
    }
}

class WaxOn implements Runnable{
    private Car car;

    WaxOn(Car car) {
        this.car = car;
    }

    @Override
    public void run() {

        try {
            wax();
            waitingForBuffer();
        } catch (InterruptedException e) {
//            e.printStackTrace();
        }

    }

    private void wax() throws InterruptedException {
        Thread.sleep(100);
        car.setWaxed(true);

        print(" WAXED.");
    }
    private void waitingForBuffer() throws InterruptedException {
        car.waitForBuffer();
    }

    private void print(String result){
        System.out.println(System.currentTimeMillis() + result);
    }
}

class WaxOff implements Runnable{
    private Car car;

    WaxOff(Car car) {
        this.car = car;
    }

    @Override
    public void run() {
        try {
            waitingForWax();buffer();
        } catch (InterruptedException e) {
//            e.printStackTrace();
        }


    }

    private void buffer() throws InterruptedException {
        Thread.sleep(100);
        car.setBuffered(true);
        print(" BUFFERED.");
    }
    private void waitingForWax() throws InterruptedException {
        car.waitForWax();
    }

    private void print(String result){
        System.out.println(System.currentTimeMillis() + result);
    }
}

class Car{
    private Boolean waxed = false;
    private Boolean buffered = false;

    public Boolean getWaxed() {
        return waxed;
    }

    synchronized public void setWaxed(Boolean waxed) {
        this.waxed = waxed;
        notify();
    }

    public Boolean getBuffered() {
        return buffered;
    }

    synchronized public void setBuffered(Boolean buffered) {
        this.buffered = buffered;
        notify();
    }

    synchronized public void waitForBuffer() throws InterruptedException {
        if(!buffered){
            wait();
        }

    }

    synchronized public void waitForWax() throws InterruptedException {
        if(!waxed){
            wait();
        }
    }
}